home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / IFC_112 / netscape / application / ContainerView.java < prev    next >
Encoding:
Text File  |  1999-05-28  |  17.3 KB  |  563 lines  |  [TEXT/CWIE]

  1. // ContainerView.java
  2. // By Ned Etcode
  3. // Copyright 1995, 1996, 1997 Netscape Communications Corp.  All rights reserved.
  4.  
  5. package netscape.application;
  6.  
  7.  
  8. // ALERT!!!s
  9. // Should we archive the title textField?
  10.  
  11. import netscape.util.*;
  12.  
  13. /** View subclass that fills itself with a Color or an Image, and can draw a
  14.   * Border around its perimeter.  The Image can be centered, scaled, or
  15.   * tiled.
  16.   * @note 1.0 Removed Component interface
  17.   * @note 1.0 minSize is now boundingbox of contained views
  18.   * @note 1.0 all draws->dirtyRect
  19.   * @note 1.0 layout removes title view before being called
  20.   * @note 1.0 Added FormElement interface for browser needs
  21.   */
  22. public class ContainerView extends View implements FormElement {
  23.     private String      title = "";
  24.     private Font        titleFont;
  25.     private Image       image;
  26.     private TextField   titleField;
  27.     private Color       backgroundColor = Color.lightGray;
  28.     private Color       titleColor = Color.black;
  29.     private Border      border = BezelBorder.groovedBezel();
  30.     private int         imageDisplayStyle = Image.CENTERED;
  31.     private boolean     transparent = false;
  32.  
  33.     static Vector    _fieldDescription = null;
  34.  
  35.     final static String TITLE_KEY = "title";
  36.     final static String TITLE_FONT_KEY = "titleFont";
  37.     final static String BACKGROUND_COLOR_KEY = "backgroundColor";
  38.     final static String TITLE_COLOR_KEY = "titleColor";
  39.     final static String BORDER_KEY = "border";
  40.     final static String IMAGE_KEY = "image";
  41.     final static String IMAGE_DISPLAY_STYLE_KEY = "imageDisplayStyle";
  42.     final static String TRANSPARENT_KEY = "transparent";
  43.  
  44.  
  45. /* constructors */
  46.  
  47.     /** Constructs a ContainerView with origin (0, 0) and zero width and
  48.       * height.
  49.       */
  50.     public ContainerView() {
  51.         this(0, 0, 0, 0);
  52.     }
  53.  
  54.     /** Constructs a ContainerView with bounds <B>rect</B>.
  55.       */
  56.     public ContainerView(Rect rect) {
  57.         this(rect.x, rect.y, rect.width, rect.height);
  58.     }
  59.  
  60.     /** Constructs a ContainerView with
  61.       * bounds (<B>x</B>, <B>y</B>, <B>width</B>, <B>height</B>).
  62.       */
  63.     public ContainerView(int x, int y, int width, int height) {
  64.         super(x, y, width, height);
  65.  
  66.  
  67.         titleField = new TextField(0, 0, 10, 18);
  68.         titleField.setBorder(null);
  69.         titleField.setTransparent(true);
  70.         titleField.setEditable(false);
  71.         titleField.setVertResizeInstruction(View.BOTTOM_MARGIN_CAN_CHANGE);
  72.         titleField.setHorizResizeInstruction(View.WIDTH_CAN_CHANGE);
  73.         titleField.setJustification(Graphics.CENTERED);
  74.  
  75.         titleFont = Font.fontNamed("Helvetica", Font.BOLD, 12);
  76.         layoutParts();
  77.     }
  78.  
  79.     void layoutParts() {
  80.         int leftM, rightM;
  81.         titleField.removeFromSuperview();
  82.  
  83.         titleField.setStringValue(title);
  84.         titleField.setFont(titleFont);
  85.         titleField.sizeToMinSize();
  86.  
  87.         if(border != null)  {
  88.             leftM = border.leftMargin();
  89.             rightM = border.rightMargin();
  90.         } else  {
  91.             leftM = 0;
  92.             rightM = 0;
  93.         }
  94.  
  95.         if (!titleField.isEmpty()) {
  96.             titleField.moveTo(leftM, 0);
  97.             titleField.sizeTo(width() - leftM - rightM, titleField.height());
  98.             addSubview(titleField);
  99.         }
  100.     }
  101.  
  102.     /** Returns the ContainterView's minimum size, which is governed by the
  103.       * space needed to fully all it's subviews.  Absolute minimum size is
  104.       * (2, 2).
  105.       */
  106.     public Size minSize()
  107.     {
  108.         Size basesize = super.minSize();
  109.         Vector subviews = this.subviews();
  110.         int maxx = 0, maxy=0, i, count;
  111.         View v;
  112.  
  113.         // Respect a setMinSize() if there is one
  114.         if(basesize.width != 0 || basesize.height != 0)
  115.             return basesize;
  116.  
  117.         // Determine the minSize for the titleField
  118.         if(title != null && !("".equals(title)))    {
  119.             titleField.setStringValue(title);
  120.             titleField.setFont(titleFont);
  121.             maxx = titleField.minSize().width + 6;
  122.             maxy = titleField.minSize().height + 2;
  123.         }
  124.  
  125.         // Force all the children to be arranged.
  126.         layoutView(0,0);
  127.  
  128.         // loop through all the children, and find the maximum
  129.         // coordinates for the lower-right corner of the view.
  130.         count = subviews.count();
  131.         for(i = 0; i < count; i++) {
  132.             v = (View)subviews.elementAt(i);
  133.             if (v.bounds().maxX() > maxx)
  134.                 maxx = v.bounds().maxX();
  135.             if (v.bounds().maxY() > maxy)
  136.                 maxy = v.bounds().maxY();
  137.         }
  138.  
  139.         basesize.width = maxx;
  140.         basesize.height = maxy;
  141.  
  142.         // Adjust for the border
  143.         if (border != null) {
  144.             basesize.width += border.rightMargin();
  145.             basesize.height += border.bottomMargin();
  146.         }
  147.  
  148.         return basesize;
  149.     }
  150.  
  151.  
  152.     /** Returns the area not used by the ContainerView to draw its bounds
  153.       * and title.
  154.       */
  155.     public Rect interiorRect() {
  156.         Rect    tmpRect;
  157.  
  158.         if (border != null)
  159.             tmpRect = border.interiorRect(0, 0, width(), height());
  160.         else
  161.             tmpRect = new Rect(0, 0, width(), height());
  162.  
  163.         if (titleField._superview != null) {
  164.             tmpRect.y += titleField.bounds.height;
  165.             tmpRect.height -= titleField.bounds.height;
  166.         }
  167.  
  168.         return tmpRect;
  169.     }
  170.  
  171.     /** Sets the ContainerView's title string and then calls its
  172.       * <B>draw()</B> method to redraw it.  If you do not want to immediately
  173.       * redraw the ContainerView, you should first call its
  174.       * <B>disableDrawing()</B> method.
  175.       * @see View#disableDrawing
  176.       */
  177.     public void setTitle(String aString) {
  178.         if (aString != null) {
  179.             title = aString;
  180.         } else {
  181.             title = "";
  182.         }
  183.         layoutParts();
  184.         setDirty(true);
  185.     }
  186.  
  187.     /** Returns the ContainerView's title.
  188.       * @see #setTitle
  189.       */
  190.     public String title() {
  191.         return title;
  192.     }
  193.  
  194.     /** Sets the ContainerView's title string Color and then calls its
  195.       * <B>draw()</B> method to redraw it.  If you do not want to immediately
  196.       * redraw the ContainerView, you should first call its
  197.       * <B>disableDrawing()</B> method.
  198.       * @see #setTitle
  199.       * @see View#disableDrawing
  200.       */
  201.     public void setTitleColor(Color aColor) {
  202.         if (aColor == null || aColor.equals(titleColor)) {
  203.             return;
  204.         }
  205.  
  206.         titleColor = aColor;
  207.         titleField.setTextColor(aColor);
  208.         setDirty(true);
  209.     }
  210.  
  211.     /** Returns the ContainerView's title string Color.
  212.       * @see #setTitleColor
  213.       */
  214.     public Color titleColor() {
  215.         return titleColor;
  216.     }
  217.  
  218.     /** Sets the ContainerView's title string Font and then calls its
  219.       * <B>draw()</B> method to redraw it.  If you do not want to immediately
  220.       * redraw the ContainerView, you should first call its
  221.       * <B>disableDrawing()</B> method.
  222.       * @see #setTitle
  223.       * @see View#disableDrawing
  224.       */
  225.     public void setTitleFont(Font aFont) {
  226.         if (aFont == null) {
  227.             titleFont = Font.fontNamed("Helvetica", Font.BOLD, 12);
  228.         } else {
  229.             titleFont = aFont;
  230.         }
  231.         layoutParts();
  232.         setDirty(true);
  233.     }
  234.  
  235.     /** Returns the ContainerView's title string Font.
  236.       * @see #setTitleFont
  237.       */
  238.     public Font titleFont() {
  239.         return titleFont;
  240.     }
  241.  
  242.     /** Sets the ContainerView's background Color and then calls its
  243.       * <B>draw()</B> method to redraw it.  If you do not want to immediately
  244.       * redraw the ContainerView, you should first call its
  245.       * <B>disableDrawing()</B> method.
  246.       * @see View#disableDrawing
  247.       */
  248.     public void setBackgroundColor(Color aColor) {
  249.         backgroundColor = aColor;
  250.         setDirty(true);
  251.     }
  252.  
  253.     /** Returns the ContainerView's background Color.
  254.       * @see #setBackgroundColor
  255.       */
  256.     public Color backgroundColor() {
  257.         return backgroundColor;
  258.     }
  259.  
  260.     /** Sets the ContainerView's Border and then calls its
  261.       * <B>draw()</B> method to redraw it.  If you do not want to immediately
  262.       * redraw the ContainerView, you should first call its
  263.       * <B>disableDrawing()</B> method.
  264.       * @see View#disableDrawing
  265.       */
  266.     public void setBorder(Border newBorder) {
  267.         if (newBorder == null) {
  268.             newBorder = EmptyBorder.emptyBorder();
  269.         }
  270.  
  271.         border = newBorder;
  272.         layoutParts();
  273.         setDirty(true);
  274.     }
  275.  
  276.     /** Returns the ContainerView's Border.
  277.       * @see #setBorder
  278.       */
  279.     public Border border() {
  280.         return border;
  281.     }
  282.  
  283.     /** Sets the ContainerView's Image and then calls its
  284.       * <B>draw()</B> method to redraw it.  If you do not want to immediately
  285.       * redraw the ContainerView, you should first call its
  286.       * <B>disableDrawing()</B> method.
  287.       * @see #setImageDisplayStyle
  288.       * @see View#disableDrawing
  289.       */
  290.     public void setImage(Image anImage) {
  291.         image = anImage;
  292.         setDirty(true);
  293.     }
  294.  
  295.     /** Returns the ContainerView's Image.
  296.       * @see #setImage
  297.       */
  298.     public Image image() {
  299.         return image;
  300.     }
  301.  
  302.     /** Sets the style the ContainerView uses to display its Image
  303.       * (Image.CENTERED, Image.TILED, or Image.SCALED).
  304.       * @see #setImage
  305.       */
  306.     public void setImageDisplayStyle(int aStyle) {
  307.         if (aStyle != Image.CENTERED && aStyle != Image.TILED &&
  308.             aStyle != Image.SCALED) {
  309.             throw new InconsistencyException("Unknown image display style: " +
  310.                 aStyle);
  311.         }
  312.  
  313.         imageDisplayStyle = aStyle;
  314.         setDirty(true);
  315.     }
  316.  
  317.     /** Returns the style the ContainerView uses to display its Image.
  318.       * @see #setImageDisplayStyle
  319.       */
  320.     public int imageDisplayStyle() {
  321.         return imageDisplayStyle;
  322.     }
  323.  
  324.     /** Sets the ContainerView to be transparent or opaque.
  325.       */
  326.     public void setTransparent(boolean flag) {
  327.         transparent = flag;
  328.     }
  329.  
  330.     /** Overridden to return <b>true</b> if the ContainerView is transparent.
  331.       * This will also return true if we have a title.
  332.       * @see #setTransparent
  333.       */
  334.     public boolean isTransparent() {
  335.         return transparent || !titleField.isEmpty();
  336.     }
  337.  
  338.     /** Draws the ContainerView's background, using its Image and
  339.       * background Color.  If the ContainerView is transparent, or its
  340.       * background Color is <b>null</b>, it only draws the Image.
  341.       * You never call this method directly, but
  342.       * should override it to produce custom background drawing.
  343.      */
  344.     public void drawViewBackground(Graphics g) {
  345.         Rect    tmpRect;
  346.  
  347.         /* draw background color only if color has been set and image doesn't
  348.          * completely fill our bounds
  349.          */
  350.         if (!transparent && (image == null ||
  351.             imageDisplayStyle == Image.CENTERED && backgroundColor != null)) {
  352.  
  353.             if (image == null) {
  354.                 tmpRect = Rect.newRect();
  355.             } else {
  356.                 tmpRect = Rect.newRect(0, 0, image.width(), image.height());
  357.             }
  358.             if (!tmpRect.contains(bounds)) {
  359.                 tmpRect.setBounds(0, 0, width(), height());
  360.                 if (titleField.isInViewHierarchy()) {
  361.                     tmpRect.moveBy(0, titleField.bounds.height / 2);
  362.                     tmpRect.sizeBy(0, -titleField.bounds.height / 2);
  363.                 }
  364.                 g.setColor(backgroundColor);
  365.                 g.fillRect(tmpRect);
  366.             }
  367.             Rect.returnRect(tmpRect);
  368.         }
  369.  
  370.         if (image != null) {
  371.             image.drawWithStyle(g, 0, 0, width(), height(), imageDisplayStyle);
  372.         }
  373.     }
  374.  
  375.     /** Draws the ContainerView's Border, including its title.  You never call
  376.       * this method directly, but should override it to produce custom
  377.       * border drawing.
  378.       * @see #setBorder
  379.       * @see #setTitle
  380.       */
  381.     public void drawViewBorder(Graphics g) {
  382.         Rect    borderRect, titleRect, clipRect;
  383.         Size    titleSize;
  384.  
  385.         if (border == null)
  386.             return;
  387.  
  388.         borderRect = Rect.newRect(0, 0, width(), height());
  389.  
  390.         if (titleField.isInViewHierarchy()) {
  391.             borderRect.moveBy(0, titleField.bounds.height / 2);
  392.             borderRect.sizeBy(0, -titleField.bounds.height / 2);
  393.         }
  394.  
  395.         /* avoid drawing the border where the title will show up.  If the
  396.          * title isn't to be drawn, then things are nice and easy.
  397.          */
  398.         if (!titleField.isInViewHierarchy()) {
  399.             border.drawInRect(g, borderRect);
  400.             Rect.returnRect(borderRect);
  401.             return;
  402.         }
  403.  
  404.         titleSize = titleField.minSize();
  405.         titleRect = Rect.newRect(titleField.bounds);
  406.         titleRect.x = titleRect.midX() - titleSize.width / 2 - 4;
  407.         titleRect.width = titleSize.width + 8;
  408.  
  409.         clipRect = Rect.newRect(borderRect);
  410.  
  411.         /* draw the left part of the border */
  412.         clipRect.width = titleRect.x - borderRect.x;
  413.  
  414.         g.pushState();
  415.         g.setClipRect(clipRect);
  416.         border.drawInRect(g, borderRect);
  417.         g.popState();
  418.  
  419.         /* draw the right part */
  420.         clipRect.x = titleRect.maxX();
  421.         clipRect.width = borderRect.maxX() - titleRect.maxX();
  422.         g.pushState();
  423.         g.setClipRect(clipRect);
  424.         border.drawInRect(g, borderRect);
  425.         g.popState();
  426.  
  427.         /* draw the bottom part */
  428.         clipRect.x = titleRect.x;
  429.         clipRect.y = titleRect.maxY();
  430.         clipRect.width = titleRect.width;
  431.         clipRect.height = borderRect.maxY() - titleRect.maxY();
  432.         g.pushState();
  433.         g.setClipRect(clipRect);
  434.         border.drawInRect(g, borderRect);
  435.         g.popState();
  436.  
  437.         Rect.returnRect(clipRect);
  438.         Rect.returnRect(titleRect);
  439.         Rect.returnRect(borderRect);
  440.     }
  441.  
  442.     /** Draws the ContainerView's background.  Calls
  443.       * <b>drawViewBackground()</b>.
  444.       * @see #drawViewBackground
  445.       */
  446.     public void drawView(Graphics g) {
  447.         drawViewBackground(g);
  448.     }
  449.  
  450.     /** Draws the ContainerView's border, after drawing its subviews.  Calls
  451.       * <b>drawViewBorder()</b>.
  452.       * @see #drawViewBorder
  453.       */
  454.     public void drawSubviews(Graphics g) {
  455.         super.drawSubviews(g);
  456.         drawViewBorder(g);
  457.     }
  458.  
  459.  
  460.     /** Overridden to get the titleField out of the way, before
  461.       * a LayoutManager can get a hold of it and mangle it's location.
  462.       * It is put back afterwards if necessary.
  463.       */
  464.     public void layoutView(int deltaX, int deltaY)  {
  465.         if(titleField.isInViewHierarchy())
  466.             titleField.removeFromSuperview();
  467.         super.layoutView(deltaX, deltaY);
  468.         layoutParts();
  469.     }
  470.  
  471. /* archiving */
  472.  
  473.  
  474.  
  475.     /** Describes the ContainerView class' information.
  476.       * @see Codable#describeClassInfo
  477.       */
  478.     public void describeClassInfo(ClassInfo info) {
  479.         super.describeClassInfo(info);
  480.  
  481.         info.addClass("netscape.application.ContainerView", 1);
  482.         info.addField(TITLE_KEY, STRING_TYPE);
  483.         info.addField(TITLE_FONT_KEY, OBJECT_TYPE);
  484.         info.addField(BACKGROUND_COLOR_KEY, OBJECT_TYPE);
  485.         info.addField(TITLE_COLOR_KEY, OBJECT_TYPE);
  486.         info.addField(IMAGE_KEY, OBJECT_TYPE);
  487.         info.addField(IMAGE_DISPLAY_STYLE_KEY, INT_TYPE);
  488.         info.addField(BORDER_KEY, OBJECT_TYPE);
  489.         info.addField(TRANSPARENT_KEY, BOOLEAN_TYPE);
  490.     }
  491.  
  492.     /** Encodes the ContainerView instance.
  493.       * @see Codable#encode
  494.       */
  495.     public void encode(Encoder encoder) throws CodingException {
  496.         boolean         addField = false;
  497.  
  498.         if (titleField.superview() != null) {
  499.             titleField.removeFromSuperview();
  500.             addField = true;
  501.         }
  502.  
  503.         super.encode(encoder);
  504.  
  505.         encoder.encodeString(TITLE_KEY, title);
  506.         encoder.encodeObject(TITLE_FONT_KEY, titleFont);
  507.         encoder.encodeObject(BACKGROUND_COLOR_KEY, backgroundColor);
  508.         encoder.encodeObject(TITLE_COLOR_KEY, titleColor);
  509.         encoder.encodeObject(IMAGE_KEY, image);
  510.         encoder.encodeInt(IMAGE_DISPLAY_STYLE_KEY, imageDisplayStyle);
  511.  
  512.         if (border instanceof EmptyBorder) {
  513.             encoder.encodeObject(BORDER_KEY, null);
  514.         } else {
  515.             encoder.encodeObject(BORDER_KEY, border);
  516.         }
  517.  
  518.         encoder.encodeBoolean(TRANSPARENT_KEY, transparent);
  519.  
  520.         if (addField) {
  521.             addSubview(titleField);
  522.         }
  523.     }
  524.  
  525.     /** Decodes the ContainerView instance.
  526.       * @see Codable#decode
  527.       */
  528.     public void decode(Decoder decoder) throws CodingException {
  529.         super.decode(decoder);
  530.  
  531.         title = decoder.decodeString(TITLE_KEY);
  532.         setTitleFont((Font)decoder.decodeObject(TITLE_FONT_KEY));
  533.         backgroundColor = (Color)decoder.decodeObject(BACKGROUND_COLOR_KEY);
  534.         setTitleColor((Color)decoder.decodeObject(TITLE_COLOR_KEY));
  535.         image = (Image)decoder.decodeObject(IMAGE_KEY);
  536.         imageDisplayStyle = decoder.decodeInt(IMAGE_DISPLAY_STYLE_KEY);
  537.         setBorder((Border)decoder.decodeObject(BORDER_KEY));
  538.         transparent = decoder.decodeBoolean(TRANSPARENT_KEY);
  539.     }
  540.  
  541.     /** Finishes the ContainerView instance decoding.
  542.       * @see Codable#finishDecoding
  543.       */
  544.     public void finishDecoding() throws CodingException {
  545.         String  unarchTitle;
  546.  
  547.         super.finishDecoding();
  548.  
  549.         unarchTitle = title;
  550.         title = null;
  551.         setTitle(unarchTitle);
  552.     }
  553.  
  554.     /** Implementation of the FormElement interface
  555.       *
  556.       */
  557.     public String formElementText() {
  558.         if(titleField != null)
  559.             return titleField.stringValue();
  560.         return "";
  561.     }
  562. }
  563.